# @Time    : 2022/9/23 10:29
# @Author  : 南黎
# @FileName: 2.线性SVM分类模型.py

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from sklearn import preprocessing
from sklearn.datasets import load_iris # 导入鸢尾花数据集
from sklearn.svm import SVC #使用支持向量机算法

#封装一个模型训练函数，输入数据文件名即可完成训练并绘制图片
def my_train(datafile):
    data=pd.read_csv(datafile).values
    #数据归一化
    max_abs_scaler = preprocessing.MaxAbsScaler()  # 注册一个预处理对象
    data = max_abs_scaler.fit_transform(data)  # fit_transform(X[, y])	适合数据，然后转换它。
    X=data[:,0:2]
    y=data[:,2].astype('int')

    clf = SVC(C=1,kernel='linear',decision_function_shape='ovo')#内核类型为线性
    #C：浮动，可选（默认=1.0）误差项的惩罚参数 C。
    #kernel：指定要在算法中使用的内核类型。它必须是“linear”、“poly”、“rbf”、“sigmoid”、“precomputed”或可调用对象之一。如果没有给出，将使用 'rbf'。如果给定了可调用对象，则它用于从数据矩阵中预先计算内核矩阵；该矩阵应该是一个 shape 数组(n_samples, n_samples)。
    # linear：选择线性函数；
    # polynomial：选择多项式函数；
    # rbf：选择径向基函数；
    # sigmoid：选择 Logistics 函数作为核函数；
    # precomputed：使用预设核值矩阵，
    # SVC 类默认以径向基函数作为核函数。
    # decision_function_shape :默认决策函数分界线形状 ‘ovo’, ‘ovr’ or None, default=None
    #fit_intercept：布尔值，默认值 真：指定是否应将常数（也称为偏差或截距）添加到决策函数中。

    # 训练模型,使用fit喂入数据X,y，即特征值和标签
    clf.fit(X, y)
    # 预测分类
    result=clf.predict(X)
    # 对模型进行评分
    score=clf.score(X,y)
    print(datafile+"线性SVM评分",score)
    plt.figure()
    # 分割图1行1列第一个图
    plt.subplot(111)
    # 选择X特征1和特征2进行绘图
    plt.scatter(X[:,0],X[:,1],c =y.reshape((-1)),edgecolor='k',s=50)

    plt.savefig("2/"+datafile + "线性SVM分类图.png")
    plt.show()
my_train("data1_ch5.csv")
my_train("data2_ch5.csv")
my_train("ex533.csv")
